:- module(organization_access, [
        organization_name/3,
        organization_email/3,
        organization_telephone/3,
        organization_webpage/3,
        organization_notes/3,
        organization_update/3,
        organization_check/2,
%% Types
        organization/1,
        organization_field/1
        ], [assertions,basicmodes,regtypes]).

:- comment(title, "Handling Information About Organizations").
:- comment(subtitle, "AMOS Project").

:- comment(author, "Manuel Carro and the CLIP group").
:- comment(author, "Facultad de Inform@'{a}tica").
:- comment(author, "Universidad Polit@'{e}cnica de Madrid").
:- comment(author, "@tt{clip@@dia.fi.upm.es}").
:- comment(author, "@tt{http://www.clip.dia.fi.upm.es/}").

:- comment(module, "

The class \"Organization\" abstracts real organizations (companies,
universities, or even user groups), and ultimately reflects an user's
affiliation.  An organization provides a means to locate and identify
	a single user (which can be thought of as an extension of an
organization) or a group of users who are somehow associated and work
or produce software under the same umbrella.

The operations herein included are aimed at creating and consulting
instances of the @em{organization} class.  They may change (for
example, to include more operations) should the ontology evolve in
that direction.


@include{three_argument_explanation.lpdoc}

@sp

@include{../Doc/acknowledgements.lpdoc}

@newpage
").

:- include(db('argnamesv/argnamesv')).   % Kludge to use local version
:- use_module(library(sort)).
:- use_module(db(basic_types)).
:- use_module(db(general_check)).


:- argnames is_an_organization(
        name, 
        email,
        telephone,
        webpage,
        notes).

fields_and_types([
        field(name,      (nonnull, atom)),
        field(email,     (null ; list(atom))),
        field(telephone, (null ; list(atom))),
        field(webpage,   (null ; list(atom))),
        field(notes,     (null ; list(atom)))
                 ]).

:- regtype organization_field(?Field)

 # "@var{Field} is a field of an organization.".


organization_field(Field):- member(Field, is_an_organization$argnames).

:- regtype organization(?Org) # "@var{Org} is an organization.".

organization(is_an_organization${}).


:- pred organization_name(Org, Name, NewOrg):
        organization * string * organization

# "@var{Description} is the description of the organization
@var{NewOrg}. There should be a defined @var{Name} in each
organization".

organization_name(Org, Name, NewOrg):-
	organization_update(Org,[name-Name],NewOrg).


:- pred organization_email(Org, Emails, NewOrg):
        organization * list(string) * organization

# "@var{Emails} is a list of contact emails for the organization
@var{NewOrg}.  @var{Emails} may be the empty list".

organization_email(Org, Email, NewOrg):-
	organization_update(Org,[email-Email],NewOrg).


:- pred organization_telephone(Org, Telephones, NewOrg): 
        organization * list(string) * organization

# "@var{Telephones} is a list of contact phone/fax number for the
organization @var{NewOrg}.  @var{Telephones} may be the empty list".

organization_telephone(Org, Telephone, NewOrg):-
	organization_update(Org,[telephone-Telephone],NewOrg).


:- pred organization_webpage(Org, Webpages, NewOrg):
        organization * list(string) * organization

# "@var{Webpages} is a list of Web pages for the organization
@var{NewOrg}.  @var{Webpages} may be the empty list".

organization_webpage(Org, Webpage, NewOrg):-
	organization_update(Org,[webpage-Webpage],NewOrg).


:- pred organization_notes(Org, Notes, NewOrg): 
        organization * list(string) * organization

# "@var{Notes} is a list of strings (comments regarding the
organization @var{NewOrg}).  @var{Notes} may be the empty list".

organization_notes(Org, Notes, NewOrg):-
	organization_update(Org,[notes-Notes],NewOrg).



:- pred organization_check(?Org, ?WrongFields):
        organization * list(organization_fields)

# "The already formed organization class @var{Org} is checked against
the constraints specified in the ontology definition.  
@include{check_definition.lpdoc}".


%organization_check(_Org, _WrongFields).

organization_check(Org, WrongFields):-
        fields_and_types(F),
        check_each_field(F, Org, WrongFields).

check_each_field([], _Org, []).
check_each_field([field(F, T)|Fs], Org, W):-
        Org = is_an_organization${F => V},
        (
            check_field(T, V) ->
            W = RestW
        ;
            W = [F|RestW]
        ),
        check_each_field(Fs, Org, RestW).




:- pred organization_update(+Org, +PairList, ?NewOrg):
        organization * list(pair) * organization

# "It updates @var{Org} to give @var{NewOrg}.  @var{PairList} is a
list of pairs (see @pred{pair}): dash-separated ground terms
@tt{Field-Value}, which are meant to express the name of a field and
its updated value.  @tt{Organization update} is a general call upon
which all the rest of the @tt{update} calls rely.".

organization_update(Org, PairList, NewOrg):-
        NewOrg = is_an_organization${},               % New asset skeleton
        sort(is_an_organization$argnames, AllFields),
        keysort(PairList, SortedPairList),  %% All sorted in same order now
        update(AllFields, SortedPairList, Org, NewOrg).

update([], _, _, _).
update([Field|Fields], [Field-NewValue|ToUpdate], Org, NewOrg):-
        !,
        NewOrg = is_an_organization${Field => NewValue},
        update(Fields, ToUpdate, Org, NewOrg).
update([Field|Fields], ToUpdate, Org, NewOrg):-
        Org = is_an_organization${Field => Value}, 
        NewOrg = is_an_organization${Field => Value}, 
        update(Fields, ToUpdate, Org, NewOrg).

:- comment(version_maintenance,on).

:- comment(version(0*1+2,2003/07/04,12:55*57+'CEST'), "Changed
   use_module and include references to use directory aliases.  (Jesus
   Correas Fernandez)").

:- comment(version(0*1+1,2003/02/14,16:27*27+'CET'), "OrgAfter to
	NewOrg (Manuel Carro)").

:- comment(version(0*1+0,2003/02/13,20:49*29+'CET'), "Initial version,
	with all interfaces included.  (Manuel Carro)").

